/**********************************************************************\

 Copyright 2012 Diggory Blake

 This file is part of klip-engine

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.

\**********************************************************************/
#pragma once

#include <unordered_map>
#include <stdint.h>

class kFont;
class kEngine;
class kImage;
class kSprite;
class kGraphics;
class kBasicController;
class kStream;
class kView;

#include "kcommon.h"
#include "kbase.h"
#include "kmath.h"
#include "kblend.h"
#include "kmaterial.h"
#include "ksharedresources.h"

class kFont : public kBase, public kSharedResource<std::tstring, kGraphics> {
	friend class kSharedResourcesBase<kFont>;
	friend class kSharedResources<kFont>;
private:
	struct CharInfo {
		int image;
		kAABB aabb;
		kVec2 offset;
		float width;
	};

	struct CacheInfo {
		kImage* image;
		kVec2 offset;
		int usage;
	};

	kGraphics* _graphics;
	std::vector<kImage*> _images;
	std::map<int32_t, CharInfo> _chars;
	mutable std::map<std::tstring, CacheInfo> _cache;
	float _lineHeight;
	kSprite* _sprite;
	kBasicController* _controller;
	kView* _cacheView;
	mutable kMaterial _material;

	static const uint8_t _signature[16];

	void load(kStream* source);
	kFont(kGraphics* graphics, float lineHeight);
	kFont(kGraphics* graphics, kStream* source);
	kFont(kGraphics* graphics, const std::tstring& uri);
	~kFont();

	static const bool AllowShare = true;
	static kFont* createShared(Container* container, const Key& key);
	static void destroyShared(Container* container, kFont* resource);

public:
	static kFont* create(kGraphics* graphics, float lineHeight);
	static kFont* create(kGraphics* graphics, kStream* source);
	static kFont* create(kGraphics* graphics, const std::tstring& uri);
	void destroy();

	static const uint8_t (&getSignature())[16] {
		return _signature;
	}
	inline kGraphics* getGraphics() {
		return _graphics;
	}

	void addChar(int32_t codePoint, int imageIndex, const kAABB& aabb, kVec2 offset, float width);
	void removeChar(int32_t codePoint);
	void setImage(int index, kImage* image);
	kImage* getImage(int index);
	void draw(kGraphics* graphics, const kMat3x3& transform, const std::tstring& text, const kColor& diffuse, const kBlend& blend = kBlend()) const;
	kVec2 measure(const kVec2& start, const std::tstring& text) const;
	kAABB getAABB(const kMat3x3& transform, const std::tstring& text) const;
	void save(kStream* stream) const;
	void save(const std::tstring& uri) const;
	void addGridChars(int32_t firstCodePoint, int imageIndex, int across, int down, float width);
};
